package com.badrit.core.clusteringAlgorithms
{
	import com.vizsage.as3mathlib.math.alg.Matrix;
	
	public class KMeans extends BaseClusteringAlgorithm
	{
	
				
		public function KMeans(patterns:Matrix, k:Number)
		{	
			super(patterns, k);														
		}						
		
		/**
		 * returns the cluster index of the given pattern index
		 **/
		public override function getClusterForPattern(patternIndex:int):int {
			return M[patternIndex];
		}
		
		protected override function assignPatternToCluster(patternIndex:int, cluster:int):void{
		 	M[patternIndex] = cluster;						
		}
		
		public override function applyAlgorithm():Number{			
			var iterations:int = 0;
			var prevCenters:Matrix = new Matrix(kClasses, mDimensions);
							
			centers.copy(prevCenters);			
			calculateCenters();
			
								
			while( isCenterChanged(prevCenters) 
					&& iterations < MAX_ITERATIONS){
				centers.copy(prevCenters);
				reDistributePatterns();
				calculateCenters();	
				iterations ++;			
			}			
			
			return calculateObjectiveFunction();			
		}
		
		/**
		 * Re Distribute patters based on new centers, using minimum distance
		 **/ 
		private function reDistributePatterns():void {
			
			for( var i:int = 0; i < nPatterns; i++){
				var minDistanceCenter:int = getClosestCenterToPattern(i);				
				assignPatternToCluster(i, minDistanceCenter);					
			}
		}								    	  
		
		private function isCenterChanged(prevCenters:Matrix):Boolean {
			for (var i:int = 0; i < centers.$m.length; i++){
				var center:Array = centers.$m[i] as Array;
				var prevCenter:Array = prevCenters.$m[i] as Array;
				
				for (var j:int = 0; j < center.length; j++){					
					if(Math.abs(center[j] - prevCenter[j]) > Epsolon ){
						return true;
					}
				}
			}  
			return false;			
		}
		
		

	}
}